package com.sharer.last.config;

import io.lettuce.core.ClientOptions;
import io.lettuce.core.SocketOptions;
import io.lettuce.core.TimeoutOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.util.StringUtils;

import java.time.Duration;

/**
 * Lettuce配置
 *
 * @ClassName LettuceConfig
 * @Author WangJin
 * @Date 2023/05/04/11:17
 * @Description
 * @Version 1.0
 */
@Configuration
public class LettuceConfig {
    @Bean
    public DefaultClientResources lettuceClientResources() {
        return DefaultClientResources.create();
    }

    @Bean("lettuceConnectionFactory")
    public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties, ClientResources clientResources, GenericObjectPoolConfig redisPoolConfig) {

        ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                //按照周期刷新拓扑
                .enablePeriodicRefresh(Duration.ofSeconds(10))
                //根据事件刷新拓扑
                .enableAllAdaptiveRefreshTriggers()
                .build();

        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                //redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接
                .autoReconnect(true)
                .cancelCommandsOnReconnectFailure(false)
                .disconnectedBehavior(ClientOptions.DisconnectedBehavior.DEFAULT)
                .pingBeforeActivateConnection(true)
                .timeoutOptions(TimeoutOptions.enabled(redisProperties.getTimeout()))
                .topologyRefreshOptions(topologyRefreshOptions)
                .socketOptions(SocketOptions.builder().connectTimeout(redisProperties.getTimeout()).keepAlive(true).build())
                .build();

        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .clientResources(clientResources)
                .clientOptions(clusterClientOptions)
                .commandTimeout(redisProperties.getTimeout())
                .shutdownTimeout(redisProperties.getLettuce().getShutdownTimeout())
                .poolConfig(redisPoolConfig)
                .build();

        if(StringUtils.isEmpty(redisProperties.getCluster())){
            //单机
            RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(redisProperties.getHost(),redisProperties.getPort());
            redisConfiguration.setDatabase(redisProperties.getDatabase());
            redisConfiguration.setPassword(redisProperties.getPassword());

            LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisConfiguration, clientConfig);
            lettuceConnectionFactory.afterPropertiesSet();
            lettuceConnectionFactory.setValidateConnection(false);

            return lettuceConnectionFactory;
        }else {
            //集群
            RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
            clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
            clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));

            LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfig, clientConfig);
            lettuceConnectionFactory.afterPropertiesSet();
            lettuceConnectionFactory.setValidateConnection(false);

            return lettuceConnectionFactory;
        }
    }

    /**
     * Redis连接池配置</b>
     */
    @Bean
    public GenericObjectPoolConfig redisPoolConfig(RedisProperties redisProperties) {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
        poolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
        poolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
        poolConfig.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWait().toMillis());
        poolConfig.setTimeBetweenEvictionRunsMillis(100);
        return poolConfig;
    }

}
